package net.xxcxcxcx.xc_enhancedmob.skills.basics.individual.rare;

import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.projectile.ProjectileUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.*;
import net.xxcxcxcx.xc_enhancedmob.config.skill.SkillConfig;
import net.xxcxcxcx.xc_enhancedmob.packet.CustomParticlePacket;
import net.xxcxcxcx.xc_enhancedmob.render.particle.summon.magic.circle.BaseAttackParticle;
import net.xxcxcxcx.xc_enhancedmob.render.particle.summon.magic.circle.BaseSummonMagicCircleParticle;
import net.xxcxcxcx.xc_enhancedmob.skills.BaseSkill;
import net.xxcxcxcx.xc_enhancedmob.skills.SkillRarity;

import java.util.Random;

public class ArrowRainSkill extends BaseSkill {

    Vec3d target = null;

    public ArrowRainSkill(int level) {
        super(level);
    }

    public ArrowRainSkill(NbtCompound nbtCompound) {
        super(nbtCompound);
        readbyNbtCompound(nbtCompound);
    }

    public ArrowRainSkill() {
    }

    @Override
    public SkillConfig getDefaultConfig() {
        SkillConfig skillConfig = super.getDefaultConfig();
        skillConfig.setPreparationtime(40);
        skillConfig.setCooldown(200);
        skillConfig.setInsideCooldown(5);
        skillConfig.setInsideMaxUseCount(10);
        skillConfig.setMessage(getConfigMessage(skillConfig));
        return skillConfig;
    }

    @Override
    public String getConfigMessage(SkillConfig skillConfig) {
        if (skillConfig == null) return super.getConfigMessage(null);
        return String.format("箭雨技能，向着敌人的方向发送level+3的箭矢,会有瞄准提示。准备时间 %d tick,重复次数 %d tick,内置冷却时间 %d tick,冷却时间 %d tick",
                skillConfig.getPreparationtime(), skillConfig.getInsideMaxUseCount(), skillConfig.getInsideCooldown(), skillConfig.getCooldown());
    }

    @Override
    public NbtCompound getNbtCompound() {
        NbtCompound nbtCompound = super.getNbtCompound();
        if (target != null) {
            NbtCompound tar = new NbtCompound();
            tar.putDouble("x", target.x);
            tar.putDouble("y", target.y);
            tar.putDouble("z", target.z);
            nbtCompound.put("target", tar);
        }
        return nbtCompound;
    }

    //通过nbt新建
    @Override
    public void readbyNbtCompound(NbtCompound nbtCompound) {
        super.readbyNbtCompound(nbtCompound);
        if (nbtCompound.contains("target")) {
            NbtCompound tar = nbtCompound.getCompound("target");
            double x = tar.getDouble("x");
            double y = tar.getDouble("y");
            double z = tar.getDouble("z");
            target = new Vec3d(x, y, z);
        }
    }

    public SkillRarity getSkillRarity() {
        return SkillRarity.Rare;
    }

    @Override
    public boolean canUseAbility(MobEntity mobEntity) {
        return (getSkilltime() < mobEntity.world.getTime());
    }

    public int getshoutcount() {
        return 3 + getSkillLevel();
    }

    @Override
    public boolean onAbilityUse(MobEntity mobEntity) {
        if (canUseAbility(mobEntity)) {
            if (target != null) {
                for (int i = 0; i < getshoutcount(); i++) {
                    Random random = new Random();
                    ItemStack itemStack = new ItemStack(Items.ARROW);
                    PersistentProjectileEntity persistentProjectileEntity = ProjectileUtil.createArrowProjectile(mobEntity, itemStack, 1);
                    persistentProjectileEntity.setPos(mobEntity.getX(), mobEntity.getEyeY() + 3 + Math.sqrt(getshoutcount()), mobEntity.getZ());
                    double d = target.getX() - persistentProjectileEntity.getX();
                    double e = target.getY() - persistentProjectileEntity.getY();
                    double f = target.getZ() - persistentProjectileEntity.getZ();
                    double g = MathHelper.sqrt(d * d + f * f);
                    persistentProjectileEntity.setVelocity(d, e + g * (double) 0.2f, f, 1.2f + 0.4f + getSkillLevel(), 14 - (Math.min(getSkillLevel(), 3)) * 4);
                    Vec3d vec3d1 = persistentProjectileEntity.getPos().relativize(target).normalize();
                    Vec3d vec3d2 = new Vec3d(0, 1, 0);
                    Vec3d vec3d3 = vec3d1.crossProduct(vec3d2).normalize();
                    float angle = (float) Math.acos((vec3d1.x * vec3d2.x + vec3d1.y * vec3d2.y + vec3d1.z * vec3d2.z) / (vec3d1.length() * vec3d2.length()));
                    Quaternion quaternion = new Quaternion(new Vec3f(vec3d3), -angle, false);
                    Vec3f vec3f = new Vec3f(random.nextFloat() * (float) Math.sqrt(getshoutcount()) - (float) Math.sqrt(getshoutcount()) / 2.0f, 0, random.nextFloat() * (float) Math.sqrt(getshoutcount()) - (float) Math.sqrt(getshoutcount()) / 2.0f);
                    vec3f.rotate(quaternion);
                    persistentProjectileEntity.setPos(persistentProjectileEntity.getX() + vec3f.getX(), persistentProjectileEntity.getY() + vec3f.getY(), persistentProjectileEntity.getZ() + vec3f.getZ());
                    mobEntity.world.spawnEntity(persistentProjectileEntity);
                }
                if (getSkillInsideUsecount() == 0 && mobEntity.world instanceof ServerWorld serverWorld) {
                    CustomParticlePacket.Updata(new BaseAttackParticle(0, new Vec3d(mobEntity.getX(), mobEntity.getEyeY() + 3 + Math.sqrt(getshoutcount()), mobEntity.getZ()), 100, target, 0.1f), new BlockPos(target), serverWorld);
                }
                setSkillInsideUsecount(getSkillInsideUsecount() + 1);
                if (getSkillInsideUsecount() < getInsideMaxUseCount()) {
                    setSkilltime(mobEntity.world.getTime() + getInsideCooldown());
                } else {
                    target = null;
                    setSkillInsideUsecount(0);
                    setwhetherPreparationTime(false);
                    setSkilltime(mobEntity.world.getTime() + getCooldown());
                }
            } else if (mobEntity.getTarget() != null) {
                if (!getwhetherPreparationTime()) {
                    target = new Vec3d(mobEntity.getTarget().getX(), mobEntity.getTarget().getBodyY(0.15), mobEntity.getTarget().getZ());
                    setSkilltime(mobEntity.world.getTime() + getPreparationTime());
                    setwhetherPreparationTime(true);
                    if (mobEntity.world instanceof ServerWorld serverWorld)
                        CustomParticlePacket.Updata(new BaseSummonMagicCircleParticle(0, new Vec3d(target.getX(), target.getY() + 0.1f, target.getZ()), 100), new BlockPos(target), serverWorld);
                } else {
                    target = null;
                    setSkillInsideUsecount(0);
                    setwhetherPreparationTime(false);
                    setSkilltime(mobEntity.world.getTime() + getCooldown());
                }
            }
        }
        return true;
    }
}
